using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;

namespace miciv
{
    public class Entity
    {
        protected EntityPrototype m_enProto;
        protected Hashtable m_htblComponents;
        protected List<IComponentInstance> m_lstComponents;
        protected string m_strID;

        virtual public CoreContext CoreContext
        {
            get
            {
                return this.m_enProto.CoreContext;
            }
        }

        virtual public CoreManager CoreManager
        {
            get
            {
                return this.m_enProto.CoreManager;
            }
        }

        virtual public string ID
        {
            get
            {
                return this.m_strID;
            }
        }

        public Entity()
        {
            this.m_lstComponents = new List<IComponentInstance>();
            this.m_strID = "UnknownEntity";
        }

        public void Initialize(EntityPrototype _enProto)
        {
            this.m_enProto = _enProto;
            this.m_htblComponents = new Hashtable();
            foreach (DictionaryEntry de in this.m_enProto.Components)
            {
                IComponentPrototype coProto = de.Value as IComponentPrototype;
                IComponentInstance coInstance = coProto.Manager.CreateInstance(this, coProto);
                this.m_htblComponents.Add(de.Key, coInstance);
                this.m_lstComponents.Add(coInstance);
            }
        }

        virtual public void Release()
        {
            for (int i = this.m_lstComponents.Count - 1; -1 < i; --i)
            {
                IComponentInstance coInstance = this.m_lstComponents[i];
                IComponentPrototype coProto = coInstance.Prototype;
                coProto.Manager.ReleaseInstance(coInstance);
            }
            this.m_lstComponents.Clear();
            this.m_htblComponents.Clear();
        }

        virtual public IComponentInstance GetComponentByName(string _strName)
        {
            if (false != this.m_htblComponents.ContainsKey(_strName))
            {
                return this.m_htblComponents[_strName] as IComponentInstance;
            }
            return null;
        }

        virtual public T GetComponentByType<T>() where T : class, IComponentInstance
        {
            Type type = typeof(T);
            foreach (IComponentInstance coInstance in this.m_lstComponents)
            {
                if (coInstance.GetType() == type)
                {
                    return coInstance as T;
                }
            }
            return null;
        }

        virtual public void Update(float _deltaTime)
        {
            foreach (IComponentInstance coInstance in this.m_lstComponents)
            {
                coInstance.Update(_deltaTime);
            }
        }

        virtual public void PostInitialize(XmlElement _xmlEntity)
        {
            this.m_strID = this.CoreManager.GetXmlAttributeValue(_xmlEntity, "id", this.m_strID);
            foreach (IComponentInstance coInstance in this.m_lstComponents)
            {
                // search for the component element with id attribute equals to component prototype id.
                string strXPath = string.Format("component[@id='{0}']", coInstance.Prototype.ID);
                XmlElement xmlComponent = _xmlEntity.SelectSingleNode(strXPath) as XmlElement;
                coInstance.PostInitialize(xmlComponent);
            }
        }
    }
}
